package com.histone.lilian.service;

import cn.hutool.cron.CronUtil;
import cn.hutool.cron.task.Task;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.histone.lilian.domain.entity.SysJob;
import com.histone.lilian.domain.entity.SysJobLog;
import com.histone.lilian.mapper.SysJobLogMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * 定时任务
 */
@Service
public class JobService {

    private final Log log = LogFactory.get();
    private final SysJobLogMapper sysJobLogMapper;

    @Value("${server.port}")
    private String port;

    public JobService(SysJobLogMapper sysJobLogMapper) {
        this.sysJobLogMapper = sysJobLogMapper;
    }

    /**
     * 新增任务
     */
    public void add(SysJob sysJob) {
        CronUtil.schedule("task_" + sysJob.getJobId(), sysJob.getCronExpression(), new Task() {

            public void execute() {
                run(sysJob);
            }
        });

        // 支持秒级别定时任务
        CronUtil.setMatchSecond(true);
        CronUtil.start();
        log.info("定时任务【{}】启动完成", sysJob.getJobName());
    }

    /**
     * 清除任务
     */
    public void remove(Long jobId) {
        CronUtil.remove("task_" + jobId);
        log.info("定时任务【{}】被移除", jobId);
    }

    /**
     * 执行任务
     * 过渡性实现定时功能，待 magic-api升级2.0
     * @param sysJob
     */
    public void run(SysJob sysJob) {
        SysJobLog jobLog = new SysJobLog(sysJob);
        try {
            // 调用本地接口，可以在 http://127.0.0.1:9999/magic/web/index.html 在线编辑该接口
            // todo magic-api 2.0 将支持定时任务
            String url = "http://127.0.0.1:" + port + sysJob.getInvokeTarget();
            String result = HttpUtil.get(url);
            log.info("定时任务【{}】执行结果：{}", sysJob.getJobName(), result);
            JSONObject jsonObject = JSONUtil.parseObj(result);
            // 接口返回成功
            if (jsonObject.getInt("code") == 200) {
                jobLog.setJobMessage(jsonObject.getStr("data"));
            } else {
                jobLog.setExceptionInfo(jsonObject.getStr("message"));
                jobLog.setStatus("1");
            }
        } catch (Exception e) {
            log.error("定时任务【{}】执行出错：{}", sysJob.getJobName(), e.getMessage());
            jobLog.setExceptionInfo(e.getMessage());
            jobLog.setStatus("1");
            switch (sysJob.getMisfirePolicy()) {
                case "1":
                    sysJob.setMisfirePolicy("2");
                    run(sysJob);
                    break;
                case "2":
                    sysJob.setMisfirePolicy("3");
                    run(sysJob);
                    break;
                case "3":
                    break;
            }
        } finally {
            // 保存日志
            try {
                sysJobLogMapper.insert(jobLog);
            } catch (Exception e) {
                log.error("保存调度日志【{}】失败：{}", jobLog, e.getMessage());
            }
        }

    }

}
